package com.foreveross.fetl.core.domain.freight.repository.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.springframework.stereotype.Repository;

import com.foreveross.fetl.common.HBaseTable;
import com.foreveross.fetl.common.hbase.client.HBaseHelper;
import com.foreveross.fetl.common.jpa.EntityHibernateRepository;
import com.foreveross.fetl.core.domain.freight.CsairTaobaoEntity;
import com.foreveross.fetl.core.domain.freight.hbase.AgentEntity;
import com.foreveross.fetl.core.domain.freight.repository.ICsairTaobaoRepository;
import com.foreveross.fetl.core.domain.task.SourceEntity;
import com.foreveross.fetl.util.DateUtils;
import com.foreveross.fetl.util.RowkeyUtils;

@Repository("csairTaobaoRepository")
public class CsairTaobaoRepositoryImpl extends EntityHibernateRepository
		implements ICsairTaobaoRepository {
	
	List<String> listCarrierKey =new ArrayList<String>();
	List<SourceEntity> sourceList =new ArrayList<SourceEntity>();
	List<CsairTaobaoEntity> listCasirTaoBao =new ArrayList<CsairTaobaoEntity>();

	@Override
	public List<CsairTaobaoEntity> findByCondition(Date reportDate,
			Date flightDate, String fromCity, String toCity, String flightNo,
			String channelKey, String hbaseKey) {
		StringBuffer jpql =new StringBuffer(" select csair from CsairTaobaoEntity csair where 1=1 ");
		List<Object> conditionVals = new ArrayList<Object>();
		if(reportDate!=null){
			jpql.append(" and csair.reportDate =? ");
			conditionVals.add(reportDate);
		}
		if(flightDate !=null){
			jpql.append(" and csair.flightDate =? ");
			conditionVals.add(flightDate);
		}
		if(null!=fromCity && !"".equals(fromCity)){
			jpql.append(" and csair.fromCity =? ");
			conditionVals.add(fromCity);
		}
		if(null!=toCity && !"".equals(toCity)){
			jpql.append(" and csair.toCity =? ");
			conditionVals.add(toCity);
		}
		if(null!=flightNo && !"".equals(flightNo)){
			jpql.append(" and csair.flightNo =? ");
			conditionVals.add(flightNo);
		}
		if(null!=channelKey && !"".equals(channelKey)){
			jpql.append(" and csair.channelKey =? ");
			conditionVals.add(channelKey);
		}
		if(null!=hbaseKey && !"".equals(hbaseKey)){
			jpql.append(" and csair.hbaseKey =? ");
			conditionVals.add(hbaseKey);
		}
		jpql.append(" order by csair.createTime desc ");
		return super.queryResult(jpql.toString(), conditionVals.toArray());
	}

	@Override
	public int createReport(List<String> airCompanys,
			List<String> compareChanels, String fromCity, String toCity,
			Date reportDate, Date endTime,Date flightDate) {
		
		SourceEntity sourceEntity =new SourceEntity();
		List<CsairTaobaoEntity> companyList= new ArrayList<CsairTaobaoEntity>();
		listCarrierKey.clear();
		sourceList.clear();
		listCasirTaoBao.clear();
		for(String channel : airCompanys){
			companyList= this.buildChannels(channel, fromCity, toCity, reportDate,endTime, flightDate);
			if(null!=companyList){
				CsairTaobaoEntity entity =null;
				for(CsairTaobaoEntity en:companyList){
					if(null==entity ){
						if(null!=en && en.getPrice()>0)
							entity=en;
					}else if(null!=en && en.getPrice()>0 && en.getPrice()<entity.getPrice()){
						entity=en;
					}
				}
				if(null!=entity && null!=entity.getPrice()){
					listCasirTaoBao.add(entity);
				}
			}
			 List<SourceEntity> listSource=sourceEntity.findByHbaseKey(channel);
			 if(null!=listSource && listSource.size()>0){
				 listCarrierKey.add(listSource.get(0).getCarrierKey());
				 sourceList.add(listSource.get(0));
			 }
		}
		Map<String , List<CsairTaobaoEntity>> channelAirMap= new HashMap<String , List<CsairTaobaoEntity>>();
		for(String channel: compareChanels){
			channelAirMap.put(channel, this.buildChannels(channel,  fromCity, toCity, reportDate,endTime, flightDate));
		}
		List<CsairTaobaoEntity> listCsair=new ArrayList<CsairTaobaoEntity>();
		CsairTaobaoEntity csair=null;
		if(null==listCasirTaoBao) return 0;
			for(CsairTaobaoEntity entity:listCasirTaoBao){
				boolean hasChannel = false;
				for(String str:compareChanels){
					csair=null;
					csair=this.getCsairReport(channelAirMap.get(str), entity.getFlightNo());
					if(null!=csair){
						hasChannel=true;
						csair.setPrice(entity.getPrice());
						csair.setHbaseKey(entity.getHbaseKey());
						listCsair.add(csair);
					}
				}
				if(!hasChannel) listCsair.add(entity);
			}
		return this.saveList(listCsair);
	}

	

	private CsairTaobaoEntity getCsairReport(List<CsairTaobaoEntity> list,
			String flightNo) {
		if(null==list || null==flightNo)return null;
		for(CsairTaobaoEntity en : list){
			if(flightNo.equals(en.getFlightNo())){
				return en;
			}
		}
		return null;
	}

	private List<CsairTaobaoEntity> buildChannels(String channel,
			String fromCity, String toCity, Date reportDate,Date endTime,
			Date flightDate) {
		List<CsairTaobaoEntity> listCsair =new ArrayList<CsairTaobaoEntity>();
		Calendar cStart = Calendar.getInstance();
		cStart.setTime(reportDate);
		Calendar cEnd = Calendar.getInstance();
		cEnd.setTime(endTime);
		while (cStart.before(cEnd)) {
			String startRowKey =RowkeyUtils.getRowKey(cStart.getTime(), channel, fromCity, toCity, flightDate, RowkeyUtils.START_ROW_KEY);
			String endRowKey=RowkeyUtils.getRowKey(cStart.getTime(), channel, fromCity, toCity, flightDate, RowkeyUtils.STOP_ROW_KEY);
			ResultScanner rs = null;
			try {
				rs = HBaseHelper.getRecords(HBaseTable.BASE_DATA_FLIGHT,
						startRowKey, endRowKey,new String[]{"planeinfo","agentInfos"},null);
				for (Result res : rs) {
					CsairTaobaoEntity casir= this.buildCsair(res,channel,reportDate, flightDate);
					if(null!=casir){
						listCsair.add(casir);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				if(rs != null) rs.close();
				rs = null;
			}
			cStart.add(Calendar.HOUR_OF_DAY, 1);// 开始时间加一小时
		}
		return listCsair;
	}
	
	private CsairTaobaoEntity buildCsair(Result res, String channel,
			Date reportDate, Date flightDate) {
		Map<String, Map<String, String>> curMap = HBaseHelper
				.transformHBaseRowToMap(res);
		Map<String, String> curPalneInfoMap = curMap.get("planeinfo");
		double flightPrice = Float.parseFloat(curPalneInfoMap.get("lowerPrice") != null 
				 ? curPalneInfoMap.get("lowerPrice") : "0");
		if (flightPrice <= 0) {
			return null;
		}
		if(curPalneInfoMap.get("flightId")==null) return null;
		if(curPalneInfoMap.get("flightId").indexOf("|")>0){
			curPalneInfoMap.put("flightId", curPalneInfoMap.get("flightId").substring(0, curPalneInfoMap.get("flightId").indexOf("|")));
		}
		if(curPalneInfoMap.get("flightId").indexOf(",")>0){
			curPalneInfoMap.put("flightId", curPalneInfoMap.get("flightId").substring(0, curPalneInfoMap.get("flightId").indexOf(",")));
		}
		String flightNo =curPalneInfoMap.get("flightId");
		String carrierKey =flightNo.substring(0, 2);
		
		if(channel.startsWith("0")){
			boolean isLowest=false;
			if(null==listCasirTaoBao || listCasirTaoBao.isEmpty()) return null;
			for(CsairTaobaoEntity entity :listCasirTaoBao){
				if(entity.getFlightNo().equals(flightNo)){
					isLowest=true;
				}
			}
			if(!isLowest){
				return null; //其它航空公司的航班不要
			}
		}
		
		boolean isAgent=false;
		for(String infos : curMap.keySet()){
			if(infos.equalsIgnoreCase("agentInfos")){
				isAgent=true;
				 break;
			}
		}
		AgentEntity  agent=null;
		if(isAgent){
			agent=this.getAgentEntity(curMap.get("agentInfos"));
		}
		CsairTaobaoEntity entity =new CsairTaobaoEntity();
		entity.setReportDate(DateUtils.parse(DateUtils.format(reportDate, "yyyyMMdd"), "yyyyMMdd"));
		entity.setFlightDate(DateUtils.parse(DateUtils.format(flightDate, "yyyyMMdd"), "yyyyMMdd"));
		entity.setFromCity(curPalneInfoMap.get("fromCity"));
		entity.setToCity(curPalneInfoMap.get("toCity"));
		entity.setFromCityName(curPalneInfoMap.get("fromCityName"));
		entity.setToCityName(curPalneInfoMap.get("toCityName"));
		entity.setCreateTime(new Date());
		entity.setFlightNo(flightNo);
		if(channel.startsWith("2")){
			entity.setHbaseKey(channel);
			entity.setPrice(flightPrice);
		}else{
			entity.setChannelKey(channel);
			entity.setCnannelName(curPalneInfoMap.get("grabChannel"));
			for(SourceEntity source:sourceList){
				if(carrierKey.equals(source.getCarrierKey())){
					entity.setHbaseKey(source.getHbaseKey());
					break;
				}
			}
			if(null!=agent && null!=agent.getPrice()){
				entity.setChannelPrice(agent.getPrice());
				entity.setAgentName(agent.getName());
			}
			if(null==entity.getChannelPrice()|| 0==entity.getChannelPrice()){
				entity.setChannelPrice(flightPrice);
			}
		}
		return entity;
	}

	private AgentEntity getAgentEntity(Map<String, String> agentMap) {
		int max=0;
		for(String key :agentMap.keySet()){
			if(key.startsWith("name") || key.startsWith("price")){
				String[] strs =key.split("_");
				if(!isNumeric(strs[strs.length-1])){
					continue;
				}
			  int num = Integer.parseInt(strs[strs.length-1]);
			  if(num > max){
				  max = num;
			  }
			}
		}
		List<AgentEntity> list =new ArrayList<AgentEntity>();
		for (int i = 0; i < max+1; i++) {
			AgentEntity agentEntity =new AgentEntity();
			agentEntity.setName(agentMap.get("name_"+i));
			double price=Float.parseFloat(agentMap.get("price_"+i) != null 
					 ? agentMap.get("price_"+i) : "0");
			agentEntity.setPrice(price);
			agentEntity.setAddress(agentMap.get("address_"+i));
			agentEntity.setType(Integer.parseInt(agentMap.get("agentType_"+i) != null 
					 ? agentMap.get("agentType_"+i) : "0"));
			list.add(agentEntity);
		}
		AgentEntity agent =null;
		for(AgentEntity en:list){
			if(null==agent || null==agent.getPrice() || agent.getPrice()==0){
				if( en.getType()!=0 && en.getPrice()>0){
					agent=en;
				}
			}else if(null!=en.getType() && en.getType()!=0 && null !=en.getPrice() && en.getPrice()>0 && en.getPrice()<agent.getPrice()){
				agent=en;
			}
		}
		return agent;
	}

	private int saveList(List<CsairTaobaoEntity> listCsair) {
		 if(listCsair==null || listCsair.size()<=0){
			   return 0;
		   }
		 int i=0;
		 List<CsairTaobaoEntity> oldList=new ArrayList<CsairTaobaoEntity>();
		 for(CsairTaobaoEntity entity :listCsair){
			oldList=this.findByCondition(entity.getReportDate(), entity.getFlightDate(), entity.getFromCity(), entity.getToCity(), null, entity.getChannelKey(), entity.getHbaseKey());
			if(null!=entity.getChannelKey()){
				 if(null!=oldList && !oldList.isEmpty()){
					 entity.setId(oldList.get(0).getId());
				 }else{
					 oldList=this.findByCondition(entity.getReportDate(), entity.getFlightDate(), entity.getFromCity(), entity.getToCity(), null, null, entity.getHbaseKey()); 
					 if(null!=oldList && !oldList.isEmpty()){
						 CsairTaobaoEntity oldEntity=oldList.get(0);
						 if(null==oldEntity.getChannelKey()){
							 entity.setId(oldEntity.getId()) ;
						 }
					 }
				 }
			 }else{
				 if(null!=oldList && !oldList.isEmpty()){
					 entity.setId(oldList.get(0).getId()); 
				 }
			 }
			 
			if(null!=entity.getPrice() && 0< entity.getPrice() && null!=entity.getChannelPrice() && 0< entity.getChannelPrice()){
				entity.setSpreadAmount(entity.getPrice()-entity.getChannelPrice());
				entity.setSpread(round(entity.getSpreadAmount()/entity.getPrice(),4,BigDecimal.ROUND_HALF_UP));
			}
			this.save(entity);
			i++;
		}
		return i;
	}
	
	/**
	 * 判断是否为数字    是 true
	 * @param str
	 * @return
	 */
   private   boolean isNumeric(String str){
			return str.matches("\\d*");    
		 } 
   
   /** 
   * 对double数据进行取精度. 
   * @param value  double数据. 
   * @param scale  精度位数(保留的小数位数). 
   * @param roundingMode  精度取值方式. 
   * @return 精度计算后的数据. 
   */ 
  private  double round(double value, int scale,
           int roundingMode) {  
      BigDecimal bd = new BigDecimal(value);  
      bd = bd.setScale(scale, roundingMode);  
      double d = bd.doubleValue();  
      bd = null;  
      return d;  
  }

}
